package android.slc.lib_server;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.SystemClock;
import android.slc.popup.SlcPopup2;

import androidx.annotation.NonNull;

import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.StringUtils;
import com.blankj.utilcode.util.ThreadUtils;
import com.blankj.utilcode.util.Utils;
import com.google.android.material.bottomsheet.SlcBottomSheetAlertDialog2;
import com.topjohnwu.superuser.Shell;

import java.util.LinkedHashMap;
import java.util.Map;

public class StartAppManager {
    public static final StartAppManager INSTANCE = new StartAppManager();


    private Context context;

    private final Map<String, String> packageWithActivityMap = new LinkedHashMap<>();
    private String startAppPackage;
    private int heartbeatInterval = Config.HEARTBEAT_INTERVAL;
    private int heartbeatIntervalMax = Config.HEARTBEAT_INTERVAL_MAX;


    private long preHeartbeatTime = 0;

    private final HeartbeatRunnable heartbeatRunnable;
    private final StartAppPackageRunnable startAppPackageRunnable;
    private final StartAppBackgroundRunnable startAppBackgroundRunnable;
    private boolean existRebootDesktopTask = false;

    private StartAppManager() {
        flushedStartPackageName();
        heartbeatRunnable = new HeartbeatRunnable();
        startAppPackageRunnable = new StartAppPackageRunnable();
        startAppBackgroundRunnable = new StartAppBackgroundRunnable();
    }

    public void init(Context context) {
        this.context = context;
    }

    private Context getContext() {
        if (context == null) {
            return Utils.getApp();
        }
        return context;
    }

    /**
     * 添加包名和Activity
     *
     * @param packageName
     * @param activityName
     */
    public void putPackageWithActivity(String packageName, String activityName) {
        packageWithActivityMap.put(packageName, activityName);
    }

    public void flushedStartPackageName() {
        startAppPackage = ServerConfig.getStartAppPackage();
    }

    public String getStartAppPackage() {
        return startAppPackage;
    }

    public String getActivityPackage() {
        return packageWithActivityMap.get(getStartAppPackage());
    }

    public void setHeartbeatInterval(int heartbeatInterval) {
        this.heartbeatInterval = heartbeatInterval;
    }

    public int getHeartbeatInterval() {
        return heartbeatInterval;
    }

    public void setHeartbeatIntervalMax(int heartbeatIntervalMax) {
        this.heartbeatIntervalMax = heartbeatIntervalMax;
    }

    public int getHeartbeatIntervalMax() {
        return heartbeatIntervalMax;
    }

    /**
     * 获取最大心跳间隔
     *
     * @return
     */
    private int explicitHeartbeatIntervalMax() {
        if (SystemClock.elapsedRealtime() < Config.HEARTBEAT_INTERVAL_MAX_FIRST) {
            return Config.HEARTBEAT_INTERVAL_MAX_FIRST;
        } else {
            return getHeartbeatInterval();
        }
    }


    /**
     * 根据生命周期启动app
     *
     * @return
     */
    public void startAppFromLife() {
        if (StringUtils.isEmpty(getStartAppPackage())) {
            SlcBottomSheetAlertDialog2.Builder bottomNativeAlertDialogBuilder = new SlcBottomSheetAlertDialog2.Builder(context);
            String[] packageNameArray = new String[packageWithActivityMap.size()];
            packageWithActivityMap.keySet().toArray(packageNameArray);
            bottomNativeAlertDialogBuilder.setItems(packageNameArray, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    ServerConfig.setStartAppPackage(packageNameArray[which]);
                    StartAppManager.INSTANCE.flushedStartPackageName();
                    startAppFromLife();
                }
            });
            SlcPopup2.createAlertDialogOperate().show(bottomNativeAlertDialogBuilder.create());
        }
        ensureAppRun(true);
    }


    public void ensureAppRun(boolean compulsion) {
        listeningHeartbeat();
        try {
            long currentTime = System.currentTimeMillis();
            //强制启动说明是来自回到桌面来启动的
            if (compulsion) {
                updateHeartbeat(currentTime);
                startAppFromDesktop();
                return;
            }
            //非强制启动说明是因为没收到心跳启动的
            ///达到杀死当前app条件
            if (currentTime - preHeartbeatTime > explicitHeartbeatIntervalMax()) {
                updateHeartbeat(currentTime);
                startAppFromBackground();
            }
        } catch (Exception ignored) {
        }
    }

    /**
     * 在桌面启动app
     */
    private void startAppFromDesktop() {
        //启动前取消所有任务
        StartAppManager.INSTANCE.existRebootDesktopTask = false;
        ThreadUtils.getMainHandler().removeCallbacks(startAppPackageRunnable);
        ThreadUtils.getMainHandler().removeCallbacks(startAppBackgroundRunnable);
        if (StringUtils.isEmpty(startAppPackage)) {
            return;
        }
        if (!AppUtils.isAppInstalled(startAppPackage)) {
            return;
        }
        //杀死启动的app
        killStartApp(new Shell.ResultCallback() {
            @Override
            public void onResult(@NonNull Shell.Result out) {
                //延时显示，否则会出问题
                ThreadUtils.runOnUiThreadDelayed(startAppPackageRunnable, Config.START_APP_DESKTOP_DELAY);
            }
        });
    }

    /**
     * 在后台启动app
     */
    private void startAppFromBackground() {
        killStartApp(new Shell.ResultCallback() {
            @Override
            public void onResult(@NonNull Shell.Result out) {
                //延时启动，为了让桌面有机会取消
                if (!StartAppManager.this.existRebootDesktopTask) {
                    StartAppManager.this.existRebootDesktopTask = true;
                    ThreadUtils.runOnUiThreadDelayed(startAppBackgroundRunnable, Config.START_APP_BACKGROUND_DELAY);
                }
            }
        });
    }

    /**
     * 杀死要启动的app
     *
     * @param resultCallback
     */
    private void killStartApp(Shell.ResultCallback resultCallback) {
        Shell.getShell(shell -> {
            Shell.cmd("am force-stop " + startAppPackage).submit(resultCallback);
        });
    }

    /**
     * 更新心跳时间
     */
    public void updateHeartbeat() {
        updateHeartbeat(System.currentTimeMillis());
    }

    /**
     * 更新心跳时间
     *
     * @param currentTime
     */
    private void updateHeartbeat(long currentTime) {
        preHeartbeatTime = currentTime;
    }

    /**
     * 监听心跳
     */
    private void listeningHeartbeat() {
        ThreadUtils.getMainHandler().removeCallbacks(heartbeatRunnable);
        ThreadUtils.runOnUiThreadDelayed(heartbeatRunnable, this.heartbeatInterval);
    }


    /**
     * 心跳间隔运行事件
     */
    private static class HeartbeatRunnable implements Runnable {

        @Override
        public void run() {
            StartAppManager.INSTANCE.ensureAppRun(false);
        }
    }

    private static class StartAppPackageRunnable implements Runnable {

        @Override
        public void run() {
            Intent intent = Utils.getApp().getPackageManager().getLaunchIntentForPackage(StartAppManager.INSTANCE.getStartAppPackage());
            if (intent != null) {
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                StartAppManager.INSTANCE.getContext().startActivity(intent);
            }
        }
    }

    private static class StartAppBackgroundRunnable implements Runnable {

        @Override
        public void run() {
            StartAppManager.INSTANCE.existRebootDesktopTask = false;
            Shell.getShell(shell -> {
                if (shell.isRoot()) {
                    //Shell.cmd("am start -n " + AppUtils.getAppPackageName() + "/" + DesktopActivity.class.getCanonicalName()).submit();
                    Shell.cmd("am start -n " + StartAppManager.INSTANCE.startAppPackage + "/" + StartAppManager.INSTANCE.getActivityPackage()).submit();
                }
            });
        }
    }

    public static class Config {
        //心跳间隔
        public static final int HEARTBEAT_INTERVAL = 2560;

        //心跳间隔极限
        public static final int HEARTBEAT_INTERVAL_MAX = HEARTBEAT_INTERVAL + 512;

        //心跳间隔极限，第一次，此时系统的广播太过密集，无法接收
        public static final int HEARTBEAT_INTERVAL_MAX_FIRST = 80 * 1024;

        //在桌面启动延时
        public static final int START_APP_DESKTOP_DELAY = 512;

        //在后台启动延时
        public static final int START_APP_BACKGROUND_DELAY = 2560;
    }
}
